//
// Copyright (c) 2009 All Right Reserved
//
// vl
//
// 2009-01-01
// Contains ...
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using JetBrains.Annotations;
using LargoCommon.Music;
namespace LargoCommon.Support
{
///
/// Music Xml.
///
public sealed class MusicXmlWriter {
#region Constructors
///
/// Initializes a new instance of the MusicXmlWriter class.
///
/// The given file.
public MusicXmlWriter(MusicalBundle givenFile) {
Contract.Requires(givenFile != null);
this.MusicalBundle = givenFile;
this.MusicalBlock = givenFile.Blocks.FirstOrDefault();
var musicalBlock = this.MusicalBlock;
if (musicalBlock != null) {
this.MusicalTracks = (from mt in musicalBlock.Strip.Lines orderby mt.LineIndex select mt).ToList();
}
}
///
/// Initializes a new instance of the class.
///
[UsedImplicitly]
public MusicXmlWriter() {
}
#endregion
#region Properties
///
/// Gets Musical File.
///
/// Property description.
// ReSharper disable once UnusedAutoPropertyAccessor.Local
private MusicalBundle MusicalBundle { get; }
/// Gets Musical block.
/// Property description.
/// Returns value.
private MusicalBlock MusicalBlock { get; }
/// Gets file name.
/// Property description.
/// Returns value.
private List MusicalTracks { get; }
///
/// Gets or sets MusicXml Header.
///
private MusicXmlHeader Header { get; set; }
#endregion
#region Public interface
///
/// Write Music Xml.
///
/// Stream writer.
public void WriteTo(TextWriter streamWriter) {
Contract.Requires(streamWriter != null);
//// Document type
//// "";
var decl = new XDeclaration("1.0", "utf-8", "no");
var comment = new XComment("Music Xml");
//// XProcessingInstruction pi = new XProcessingInstruction();
var doc = new XDocument(decl, comment);
//// "";
var documentType = new XDocumentType("score-partwise", "-//Recordare//DTD MusicXml 3.0 Partwise//EN", "http://www.musicxml.org/dtds/partwise.dtd", null);
doc.Add(documentType);
//// Score Partwise - doc.Root element name ="score-partwise"
var scorePartwise = new XElement(
"score-partwise",
new XAttribute("version", "3.0"));
this.Header = new MusicXmlHeader(scorePartwise, this.MusicalBlock);
this.Header.WriteXmlHeader();
var element = this.ScorePartListElement();
this.Header.ScorePartwise.Add(element);
//// ????? XElement element = this.TempoElement(); scorePartwise.Add(element);
foreach (var partElement in this.MusicalTracks.Select(this.PartElement)) {
scorePartwise.Add(partElement);
}
doc.Add(scorePartwise);
//// Saving
var outputSettings = new XmlWriterSettings { NewLineOnAttributes = true, Indent = true };
using (var xmlWriter = XmlWriter.Create(streamWriter, outputSettings)) {
doc.Save(xmlWriter);
}
}
#endregion
#region ScorePartList
///
/// Score Part List element.
///
/// Returns value.
private XElement ScorePartListElement() {
var partList = new XElement("part-list");
foreach (var track in this.MusicalBlock.Strip.Lines) {
var instr = track.FirstStatus.Instrument?.MelodicInstrument ?? MidiMelodicInstrument.AcousticGrandPiano;
if (track.FirstStatus.Instrument != null)
{
var number = track.FirstStatus.Instrument.Number;
var scorePartObject = new ScorePartObject {
Id = "P" + track.LineIndex,
PartName = instr.ToString(),
ScoreInstrumentId = "I" + number,
MidiInstrumentId = "I" + number,
InstrumentName = instr.ToString(),
MidiProgram = number,
MidiChannel = track.MainVoice.Channel
};
var scorePart = scorePartObject.ScorePart();
partList.Add(scorePart);
}
}
return partList;
}
#endregion
#region Musical Parts
///
/// Part element.
///
/// Musical track.
/// Returns value.
private XElement PartElement(MusicalLine track) {
Contract.Requires(this.MusicalBlock != null);
Contract.Requires(track != null);
var part = new XElement(
"part",
new XAttribute("id", "P" + track.LineIndex));
for (var barNumber = 1; barNumber <= this.MusicalBlock.Header.NumberOfBars; barNumber++) {
//// MusicXmlMeasure musicXmlMeasure = new MusicXmlMeasure(this.Header);
var measure = MusicXmlMeasure.MeasureElement(barNumber, track, this.MusicalBlock.Header);
part.Add(measure);
}
return part;
}
#endregion
}
}